# -*- coding:utf8 -*- #
# -----------------------------------------------------------------------------------
# ProjectName:  smart-meter-iot-test-console
# FileName:     mqttConnect.py
# Author  :     
# Datetime:     2023/4/7 23:46
# Description：MQTT连接
# -----------------------------------------------------------------------------------
import json
import struct
from time import sleep

import paho.mqtt.client as mqtt
from common.util.configUtil.configUtil import ConfigUtil
from common.util.jsonUtl.jsonUtil import JsonUtil
from common.util.logUtil.logUtil import LoggerUtil
from common.util.timeUtil.timeUtil import get_now_time
from core.mqtt.libProject.get_device_secret.getDeviceSecret import get_device_secret

logger = LoggerUtil()


def mqtt_connect(deviceName: str) -> mqtt:
    global mqttClient
    conf = ConfigUtil()
    productKey = conf.get_productkey()
    try:
        # 当连接上服务器后回调此函数
        def on_connect(client, userdata, flags, rc) -> None:
            readJson = JsonUtil()
            connectResult = readJson.read_connack(rc)
            if rc == 0:
                print(f"MQTT{connectResult}！")
                logger.debug(connectResult)
                client.subscribe(f"/sys/{productKey}/{deviceName}/rrpc/request/+")
                client.subscribe(f"/{productKey}/{deviceName}/user/get")
            else:
                print(f"MQTT连接失败,失败原因:{connectResult}")
                logger.debug(f"MQTT连接失败,失败原因:{connectResult}")

        # MQTT用户名
        mqttUserName = conf.get_mqtt_config("mqttUserName").format(deviceName, productKey)
        # MQTT链接ID
        mqttClientId = conf.get_mqtt_config("mqttClientId").format(deviceName)
        mqttHostPort = conf.get_mqtt_config("mqttHostPort")
        # 通过ID链接MQTT
        mqttClient = mqtt.Client(mqttClientId)
        getDeviceSecretJson, url = get_device_secret(deviceName)
        if getDeviceSecretJson:
            if getDeviceSecretJson["success"] is False:
                print("请输入正确的设备号段！")
                logger.warning("请输入正确的设备号段！")
                return
            elif getDeviceSecretJson["success"] is True:
                if "test" in url:
                    print('……开始连接测试环境……')
                    logger.debug("……开始连接测试环境……")
                else:
                    print('……开始连接生产环境,请谨慎操作！……')
                    logger.debug("……开始连接生产环境,请谨慎操作！……")
                mqttPassWord = getDeviceSecretJson["data"]["password"]
                mqttHostUrl = getDeviceSecretJson["data"]["mqttUrl"]
                print(f"mqttlientId:{mqttClientId}")
                logger.debug(f"mqttlientId:{mqttClientId}")
                print(f"mqttUserName:{mqttUserName}")
                logger.debug(f"mqttUserName:{mqttUserName}")
                print(f"mqttPassWord:{mqttPassWord}")
                logger.debug(f"mqttPassWord:{mqttPassWord}")
                print(f"mqttUrl:{mqttHostUrl}")
                logger.debug(f"mqttUrl:{mqttHostUrl}")
                mqttClient.username_pw_set(mqttUserName, mqttPassWord)
                mqttClient.connect(mqttHostUrl, int(mqttHostPort), keepalive=300)
                mqttClient.on_connect = on_connect
                sleep(1)
                return mqttClient
    except ValueError as ve:
        if ve.__context__ == "Invalid host.":
            print("服务连接失败！")
    except struct.error as e:
        logger.error(f"mqtt_connect:  {e}")
        mqttClient.reconnect()
    except Exception as c:
        logger.error(f"mqtt_connect:  {c}")
        mqttClient.reconnect()


# publish (发布)消息
def on_publish(client, topic, payload, qos) -> None:
    client.loop_start()
    client.publish(topic, payload, qos)


#  subscribe 订阅消息
def subscribe(client: mqtt, deviceNo):
    def on_message_come(lient, userdata, msg) -> None:
        topic = msg.topic
        deviceName = str(topic).split("/")[3]
        requestId = str(topic).split("/")[6]
        if "rrpc/request" in topic:
            relpyId = json.loads(msg.payload)["id"]
            synchronousMessage = f"{get_now_time(1)} - 同步消息接收{msg.topic}:{str(msg.payload)}"
            print(synchronousMessage)
            logger.info({synchronousMessage})
            logger.debug({synchronousMessage})
            topic = topic.replace('request', 'response')
            responseTopic = {"success": "true", "code": 200, "id": relpyId, "data": {}}
            on_publish(client, topic, str(responseTopic), 0)
            sleep(0.5)
            print(f"{get_now_time(1)} - {deviceName}： 同步指令已回复,回复内容:\n{responseTopic}")
        else:
            asynchronousMessage = f"{get_now_time(1)} - 异步消息接收{msg.topic}:{str(msg.payload)}"
            print(asynchronousMessage)
            logger.info({asynchronousMessage})
            logger.debug({asynchronousMessage})

    client.on_message = on_message_come


if __name__ == '__main__':
    conf = ConfigUtil()
    deviceName = conf.get_mqtt_config("deviceName")
    client = mqtt_connect(deviceName)
    subscribe(client, deviceName)
    client.loop_forever()
